package com.koi.satoken.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author ･ᴗ･
 * @description [Sa-Token代码方式进行配置]
 */
@Configuration
public class KoiSaTokenFilter {
//    之前的章节中，我们学习了“根据拦截器实现路由拦截鉴权”，其实在大多数web框架中，使用过滤器可以实现同样的功能，本章我们就利用Sa-Token全局过滤器来实现路由拦截器鉴权。
//
//    首先我们先梳理清楚一个问题，既然拦截器已经可以实现路由鉴权，为什么还要用过滤器再实现一遍呢？简而言之：
//
//    相比于拦截器，过滤器更加底层，执行时机更靠前，有利于防渗透扫描。
//    过滤器可以拦截静态资源，方便我们做一些权限控制。
//    部分Web框架根本就没有提供拦截器功能，但几乎所有的Web框架都会提供过滤器机制。
//    但是过滤器也有一些缺点，比如：
//
//    由于太过底层，导致无法率先拿到HandlerMethod对象，无法据此添加一些额外功能。
//    由于拦截的太全面了，导致我们需要对很多特殊路由(如/favicon.ico)做一些额外处理。
//    在Spring中，过滤器中抛出的异常无法进入全局@ExceptionHandler，我们必须额外编写代码进行异常处理。
//    Sa-Token同时提供过滤器和拦截器机制，不是为了让谁替代谁，而是为了让大家根据自己的实际业务合理选择，拥有更多的发挥空间。


    /**
     * @description [全局过滤器-只用来设置跨域资源和开启浏览器默认XSS防护]
     * @author ･ᴗ･
     */
    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
                // 前置函数：在每次认证函数之前执行
                .setBeforeAuth(r -> {
                    // ---------- 设置一些安全响应头 ----------
                    SaHolder.getResponse()
                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            .setHeader("Access-Control-Allow-Methods", "*")
                            .setHeader("Access-Control-Max-Age", "3600")
                            .setHeader("Access-Control-Allow-Headers", "*")
                            .setHeader("Content-Type", "application/json;charset=UTF-8")
                            // 服务器名称
                            .setServer("Koi-Admin")
                            // 是否可以在iframe显示视图： DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
                            .setHeader("X-Frame-Options", "SAMEORIGIN")
                            // 是否启用浏览器默认XSS防护： 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时，停止渲染页面
                            .setHeader("X-XSS-Protection", "1; mode=block")
                            // 禁用浏览器内容嗅探
                            .setHeader("X-Content-Type-Options", "nosniff");
                    // 如果是预检请求，则立即返回到前端
                    SaRouter.match(SaHttpMethod.OPTIONS)
                            .free(obj -> {
                            })
                            .back();
                });
    }

}
